package com.example.microinvestmarket.service.impl;

import com.example.microinvestcommon.entity.Stock;
import com.example.microinvestmarket.Runnable.InitializeStockDataRunnable;
import com.example.microinvestmarket.Runnable.RandomStockNameRunnable;
import com.example.microinvestcommon.pojo.Result;
import com.example.microinvestmarket.Runnable.RandomStockNumberRunnable;
import com.example.microinvestmarket.dao.InsertStockDataMapper;
import com.example.microinvestmarket.service.InitializeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author Tianwailaiwu
 * @Time 2025-4-21
 * 用于股票数据初始化服务
 */

@Service
public class InitializeServiceImpl implements InitializeService {

    // 线程池配置常量
    private static final int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors();
    private static final int MAX_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2;
    private static final int QUEUE_CAPACITY = 1000;
    private static final Long KEEP_ALIVE_TIME = 30L;

    // 股票数据生成参数
    private static final int TOTAL_TURN_NUM = 48;
    private static final int EVERY_TURN_NUM = 10;
    private static final int MAX_NUM = 80;
    private static final int MIN_NUM = 20;

    // 使用静态线程池避免重复创建
    private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(
            CORE_POOL_SIZE,
            MAX_POOL_SIZE,
            KEEP_ALIVE_TIME,
            TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(QUEUE_CAPACITY),
            new ThreadPoolExecutor.CallerRunsPolicy()
    );

    private final InsertStockDataMapper insertStockDataMapper;

    @Autowired
    public InitializeServiceImpl(InsertStockDataMapper insertStockDataMapper) {
        this.insertStockDataMapper = insertStockDataMapper;
    }

    @Transactional
    public Result<String> batchInsertStockData(Integer initializeStockNum) {
        // 1. 生成股票数据
        List<String> stockNumber = generateStockNumber(initializeStockNum); // 随机股票编号
        List<String> stockNames = generateStockNames(initializeStockNum);   // 随机股票名称
        List<List<Double>> stockData = generateStockData(initializeStockNum); // 股票趋势数据

        // 用于保存生成好的 Stock 对象列表
        List<Stock> stockList = new ArrayList<>();

        for (int i = 0; i < initializeStockNum; i++) {
            //[[data]]形式
            List<List<Double>> lists=new ArrayList<>();
            lists.add(stockData.get(i));

            String stockDataString=convertToListJson(lists);

//            String stockDataString = convertToLJson(stockData.get(i)); // 将趋势数据转为 JSON 字符串

            Stock stock = new Stock(stockNumber.get(i), stockNames.get(i), stockDataString);
            stockList.add(stock); // 加入列表等待插入
        }

        // 2. 使用 CountDownLatch 等待所有线程插入完成
        CountDownLatch latch = new CountDownLatch(initializeStockNum);

        for (int i = 0; i < stockList.size(); i++) {
            final int index = i;
            executor.execute(() -> {
                try {
                    // 线程内取出对应的 Stock 对象
                    Stock stock = stockList.get(index);

                    // 使用 Stock 对象插入数据库（这里替换为新的 insert 方法）
                    insertStockDataMapper.insertStockData(stock);

                } catch (Exception e) {
                    System.err.println("插入股票数据失败: " + stockList.get(index).getStockSymbol());
                    e.printStackTrace();
                } finally {
                    latch.countDown(); // 每个线程完成后减少计数
                }
            });
        }

        // 3. 等待所有插入线程完成或超时
        try {
            if (!latch.await(5, TimeUnit.MINUTES)) {
                return Result.error("数据插入超时");
            }
            return Result.success("成功插入 " + initializeStockNum + " 条股票数据");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return Result.error("数据插入被中断");
        }
    }


    private List<String> generateStockNumber(int count){
        RandomStockNumberRunnable.clearStockNumberList();
        CountDownLatch latch = new CountDownLatch(count);

        for (int i = 0; i < count; i++) {
            executor.execute(new RandomStockNumberRunnable() {
                @Override
                public void run() {
                    try {
                        super.run();
                    } finally {
                        latch.countDown();
                    }
                }
            });
        }

        try {
            latch.await();
            return RandomStockNumberRunnable.getStockNumberList();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("生成股票代码被中断", e);
        }
    }


    private List<String> generateStockNames(int count) {
        RandomStockNameRunnable.clearStockNameList();
        CountDownLatch latch = new CountDownLatch(count);

        for (int i = 0; i < count; i++) {
            executor.execute(new RandomStockNameRunnable() {
                @Override
                public void run() {
                    try {
                        super.run();
                    } finally {
                        latch.countDown();
                    }
                }
            });
        }

        try {
            latch.await();
            return RandomStockNameRunnable.getStockNameList();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("生成股票名称被中断", e);
        }
    }

    private List<List<Double>> generateStockData(int count) {
        InitializeStockDataRunnable.clearStockDataList();
        CountDownLatch latch = new CountDownLatch(count);

        for (int i = 0; i < count; i++) {
            executor.execute(new InitializeStockDataRunnable(
                    TOTAL_TURN_NUM, EVERY_TURN_NUM, MAX_NUM, MIN_NUM) {
                @Override
                public void run() {
                    try {
                        super.run();
                    } finally {
                        latch.countDown();
                    }
                }
            });
        }

        try {
            latch.await();
            return InitializeStockDataRunnable.getStockDataList();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("生成股票数据被中断", e);
        }
    }

    private String convertToJson(List<Double> stockData) {
        //返回String类型List
        return stockData.toString();
    }

    private String convertToListJson(List<List<Double>> stockData){
        return stockData.toString();
    }


}